package cn.edu.sdjzu.knoverse.service.impl;

import cn.edu.sdjzu.knoverse.constant.RedisGraphConstant;
import cn.edu.sdjzu.knoverse.model.dto.graph.EdgeDTO;
import cn.edu.sdjzu.knoverse.model.dto.graph.GraphDTO;
import cn.edu.sdjzu.knoverse.model.dto.graph.NodeDTO;
import cn.edu.sdjzu.knoverse.model.entity.kg.BaseNode;
import cn.edu.sdjzu.knoverse.service.GraphQueryService;
import lombok.extern.slf4j.Slf4j;
import org.neo4j.driver.Record;
import org.neo4j.driver.types.Node;
import org.neo4j.driver.types.Relationship;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.neo4j.core.Neo4jClient;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
import java.util.stream.StreamSupport;

@Service
@Slf4j
public class GraphQueryServiceImpl implements GraphQueryService {

    @Autowired
    private Neo4jClient neo4jClient;
    
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    @Override
    public GraphDTO getNodeWithNeighbors(Long nodeId) {
        Map<String, Object> params = new HashMap<>();
        params.put("nodeId", nodeId);

        // 修改查询逻辑，分为三步执行，保证正确获取邻居节点之间的关系
        // 1. 先获取中心节点
        String centerNodeQuery = 
            "MATCH (n:BaseNode) " +
            "WHERE n.nodeId = $nodeId " +
            "RETURN n";

        log.info("查询中心节点: {}, 参数: {}", centerNodeQuery, params);
        Collection<Map<String, Object>> centerNodeRecords = neo4jClient.query(centerNodeQuery)
                .bindAll(params)
                .fetch()
                .all();

        // 用于存储唯一节点和边的集合
        Map<Long, Map<String, Object>> uniqueNodes = new HashMap<>();
        Set<Map<String, Object>> uniqueEdges = new HashSet<>();

        // 确保中心节点存在
        if (centerNodeRecords.isEmpty()) {
            log.error("未找到ID为{}的节点", nodeId);
            return new GraphDTO(new ArrayList<>(), new ArrayList<>());
        }

        // 处理中心节点
        Map<String, Object> record = centerNodeRecords.iterator().next();
        if (record.get("n") != null) {
            Map<String, Object> nodeMap = getNodeProperties(record.get("n"));
            if (nodeMap != null && nodeMap.containsKey("nodeId")) {
                try {
                    uniqueNodes.put(nodeId, nodeMap);
                    log.debug("处理中心节点: {}, 属性: {}", nodeId, nodeMap);
                } catch (Exception e) {
                    log.error("处理中心节点ID时出错: {}, 错误: {}", nodeMap.get("nodeId"), e.getMessage());
                }
            }
        }

        // 2. 获取与中心节点直接相连的所有邻居节点及关系
        String neighborsQuery = 
            "MATCH (n:BaseNode)-[r]->(neighbor:BaseNode) " +
            "WHERE n.nodeId = $nodeId " +
            "RETURN n, r, neighbor, 'outgoing' as direction " +
            "UNION " +
            "MATCH (neighbor:BaseNode)-[r]->(n:BaseNode) " +
            "WHERE n.nodeId = $nodeId " +
            "RETURN n, r, neighbor, 'incoming' as direction";

        log.info("查询邻居节点及关系: {}, 参数: {}", neighborsQuery, params);
        Collection<Map<String, Object>> neighborRecords = neo4jClient.query(neighborsQuery)
                .bindAll(params)
                .fetch()
                .all();

        log.info("邻居节点查询结果记录数: {}", neighborRecords.size());

        // 处理邻居节点和关系，同时收集所有邻居节点ID
        Set<Long> neighborIds = new HashSet<>();
        for (Map<String, Object> neighborRecord : neighborRecords) {
            if (neighborRecord.get("neighbor") != null && neighborRecord.get("r") != null) {
                Map<String, Object> neighborMap = getNodeProperties(neighborRecord.get("neighbor"));
                Map<String, Object> relationshipMap = getRelationshipProperties(neighborRecord.get("r"));
                String direction = (String) neighborRecord.get("direction");
                
                if (relationshipMap != null && neighborMap != null && neighborMap.containsKey("nodeId")) {
                    try {
                        Long neighborNodeId = Long.valueOf(neighborMap.get("nodeId").toString());
                        neighborIds.add(neighborNodeId); // 收集邻居节点ID
                        uniqueNodes.put(neighborNodeId, neighborMap);
                        
                        // 根据关系方向决定源节点和目标节点
                        Long sourceId, targetId;
                        if ("outgoing".equals(direction)) {
                            sourceId = nodeId;
                            targetId = neighborNodeId;
                            log.debug("处理出向邻居节点: {}, 属性: {}", neighborNodeId, neighborMap);
                        } else {
                            sourceId = neighborNodeId;
                            targetId = nodeId;
                            log.debug("处理入向邻居节点: {}, 属性: {}", neighborNodeId, neighborMap);
                        }
                        
                        // 添加边
                        Map<String, Object> edge = new HashMap<>();
                        edge.put("sourceId", sourceId);
                        edge.put("targetId", targetId);
                        edge.put("type", relationshipMap.get("type"));
                        edge.put("name", relationshipMap.get("name"));
                        
                        uniqueEdges.add(edge);
                        log.debug("添加边: 从{}到{}, 类型: {}, 名称: {}", 
                                sourceId, targetId, relationshipMap.get("type"), relationshipMap.get("name"));
                    } catch (Exception e) {
                        log.error("处理邻居节点边时出错: {}", e.getMessage());
                    }
                }
            }
        }

        // 3. 如果找到了邻居节点，查询所有与邻居节点相关的关系
        if (!neighborIds.isEmpty()) {
            // 将邻居节点ID集合转换为参数列表
            params.put("neighborIds", new ArrayList<>(neighborIds));
            
            // 修改查询为：查询所有邻居节点出发的关系和指向邻居节点的关系（获取邻居节点与图上任何节点的关系）
            String allNeighborRelationsQuery = 
                "MATCH (n1:BaseNode)-[r]->(n2:BaseNode) " +
                "WHERE n1.nodeId IN $neighborIds " +
                "RETURN n1, r, n2 " +
                "UNION " +
                "MATCH (n1:BaseNode)-[r]->(n2:BaseNode) " +
                "WHERE n2.nodeId IN $neighborIds " +
                "RETURN n1, r, n2";

            log.info("查询邻居节点所有关系: {}, 参数: {}", allNeighborRelationsQuery, params);
            Collection<Map<String, Object>> neighborRelationsRecords = neo4jClient.query(allNeighborRelationsQuery)
                    .bindAll(params)
                    .fetch()
                    .all();

            log.info("邻居节点所有关系查询结果记录数: {}", neighborRelationsRecords.size());

            // 处理邻居节点的所有关系
            for (Map<String, Object> relRecord : neighborRelationsRecords) {
                if (relRecord.get("n1") != null && relRecord.get("n2") != null && relRecord.get("r") != null) {
                    Map<String, Object> sourceMap = getNodeProperties(relRecord.get("n1"));
                    Map<String, Object> targetMap = getNodeProperties(relRecord.get("n2"));
                    Map<String, Object> relationshipMap = getRelationshipProperties(relRecord.get("r"));
                    
                    if (relationshipMap != null && sourceMap != null && targetMap != null && 
                            sourceMap.containsKey("nodeId") && targetMap.containsKey("nodeId")) {
                        try {
                            Long sourceId = Long.valueOf(sourceMap.get("nodeId").toString());
                            Long targetId = Long.valueOf(targetMap.get("nodeId").toString());

                            // 添加边（如果源节点和目标节点不相同）
                            if (!sourceId.equals(targetId)) {
                                Map<String, Object> edge = new HashMap<>();
                                edge.put("sourceId", sourceId);
                                edge.put("targetId", targetId);
                                edge.put("type", relationshipMap.get("type"));
                                edge.put("name", relationshipMap.get("name"));
                                
                                uniqueEdges.add(edge);
                                log.info("添加邻居节点关系: 从{}到{}, 类型: {}, 名称: {}", 
                                        sourceId, targetId, relationshipMap.get("type"), relationshipMap.get("name"));
                            }
                        } catch (Exception e) {
                            log.error("处理邻居节点关系时出错: {}", e.getMessage());
                        }
                    }
                }
            }
        }

        // 构建返回结果
        GraphDTO result = buildGraphDTO(uniqueNodes, uniqueEdges);
        log.info("返回图数据: 节点数: {}, 边数: {}", 
                result.getNodes() != null ? result.getNodes().size() : 0, 
                result.getEdges() != null ? result.getEdges().size() : 0);
        return result;
    }
    
    @Override
    public GraphDTO getSubgraph(String type, String keyword) {
        Map<String, Object> params = new HashMap<>();
        params.put("type", type);
        params.put("keyword", keyword);
        
        // 步骤1: 查询匹配的中心节点
        String centerNodesQuery = 
            "MATCH (n:BaseNode) " +
            "WHERE $type IN labels(n) " +  // 使用参数绑定处理类型
            "AND (n.name CONTAINS $keyword OR n.description CONTAINS $keyword) " +
            "RETURN n " +
            "LIMIT 10"; // 限制中心节点数量

        log.info("执行子图中心节点查询: {}, 参数: {}", centerNodesQuery, params);
        
        Collection<Map<String, Object>> centerNodeRecords = neo4jClient.query(centerNodesQuery)
                .bindAll(params)
                .fetch()
                .all();

        log.info("子图中心节点查询结果记录数: {}", centerNodeRecords.size());
        
        // 用于存储唯一节点和边的集合
        Map<Long, Map<String, Object>> uniqueNodes = new HashMap<>();
        Set<Map<String, Object>> uniqueEdges = new HashSet<>();
        Set<Long> centerNodeIds = new HashSet<>(); // 存储中心节点ID
        
        // 处理中心节点查询结果
        for (Map<String, Object> record : centerNodeRecords) {
            if (record.get("n") != null) {
                Map<String, Object> nodeMap = getNodeProperties(record.get("n"));
                if (nodeMap != null && nodeMap.containsKey("nodeId")) {
                    try {
                        Long nodeId = Long.valueOf(nodeMap.get("nodeId").toString());
                        uniqueNodes.put(nodeId, nodeMap);
                        centerNodeIds.add(nodeId); // 记录中心节点ID
                        log.info("处理子图中心节点: {}, 属性: {}", nodeId, nodeMap);
                    } catch (Exception e) {
                        log.error("处理子图中心节点ID时出错: {}, 错误: {}", nodeMap.get("nodeId"), e.getMessage());
                    }
                }
            }
        }
        
        // 如果没有找到中心节点，则返回空结果
        if (centerNodeIds.isEmpty()) {
            log.info("未找到匹配的中心节点");
            return new GraphDTO(new ArrayList<>(), new ArrayList<>());
        }
        
        // 步骤2: 查询与中心节点直接相连的所有邻居节点及关系
        params.put("centerNodeIds", new ArrayList<>(centerNodeIds));
        
        String neighborsQuery = 
            "MATCH (n:BaseNode)-[r]->(neighbor:BaseNode) " +
            "WHERE n.nodeId IN $centerNodeIds " +
            "RETURN n, r, neighbor, 'outgoing' as direction " +
            "UNION " +
            "MATCH (neighbor:BaseNode)-[r]->(n:BaseNode) " +
            "WHERE n.nodeId IN $centerNodeIds " +
            "RETURN n, r, neighbor, 'incoming' as direction";

        log.info("查询邻居节点及关系: {}, 参数: {}", neighborsQuery, params);
        Collection<Map<String, Object>> neighborRecords = neo4jClient.query(neighborsQuery)
                .bindAll(params)
                .fetch()
                .all();

        log.info("邻居节点查询结果记录数: {}", neighborRecords.size());

        // 处理邻居节点和关系，同时收集所有邻居节点ID
        Set<Long> neighborIds = new HashSet<>();
        for (Map<String, Object> neighborRecord : neighborRecords) {
            if (neighborRecord.get("neighbor") != null && neighborRecord.get("r") != null && neighborRecord.get("n") != null) {
                Map<String, Object> centerNodeMap = getNodeProperties(neighborRecord.get("n"));
                Map<String, Object> neighborMap = getNodeProperties(neighborRecord.get("neighbor"));
                Map<String, Object> relationshipMap = getRelationshipProperties(neighborRecord.get("r"));
                String direction = (String) neighborRecord.get("direction");
                
                if (relationshipMap != null && neighborMap != null && centerNodeMap != null && 
                        centerNodeMap.containsKey("nodeId") && neighborMap.containsKey("nodeId")) {
                    try {
                        Long centerNodeId = Long.valueOf(centerNodeMap.get("nodeId").toString());
                        Long neighborNodeId = Long.valueOf(neighborMap.get("nodeId").toString());
                        neighborIds.add(neighborNodeId); // 收集邻居节点ID
                        uniqueNodes.put(neighborNodeId, neighborMap);
                        
                        // 根据关系方向决定源节点和目标节点
                        Long sourceId, targetId;
                        if ("outgoing".equals(direction)) {
                            sourceId = centerNodeId;
                            targetId = neighborNodeId;
                            log.debug("处理出向邻居节点: {}, 属性: {}", neighborNodeId, neighborMap);
                        } else {
                            sourceId = neighborNodeId;
                            targetId = centerNodeId;
                            log.debug("处理入向邻居节点: {}, 属性: {}", neighborNodeId, neighborMap);
                        }
                        
                        // 添加边
                        Map<String, Object> edge = new HashMap<>();
                        edge.put("sourceId", sourceId);
                        edge.put("targetId", targetId);
                        edge.put("type", relationshipMap.get("type"));
                        edge.put("name", relationshipMap.get("name"));
                        
                        uniqueEdges.add(edge);
                        log.debug("添加边: 从{}到{}, 类型: {}, 名称: {}", 
                                sourceId, targetId, relationshipMap.get("type"), relationshipMap.get("name"));
                    } catch (Exception e) {
                        log.error("处理邻居节点边时出错: {}", e.getMessage());
                    }
                }
            }
        }

        // 步骤3: 如果找到了邻居节点，查询邻居节点之间的关系
        if (!neighborIds.isEmpty()) {
            // 将邻居节点ID集合转换为参数列表
            params.put("neighborIds", new ArrayList<>(neighborIds));
            
            // 修改查询为：查询所有邻居节点出发的关系和指向邻居节点的关系（获取邻居节点与图上任何节点的关系）
            String allNeighborRelationsQuery = 
                "MATCH (n1:BaseNode)-[r]->(n2:BaseNode) " +
                "WHERE n1.nodeId IN $neighborIds " +
                "RETURN n1, r, n2 " +
                "UNION " +
                "MATCH (n1:BaseNode)-[r]->(n2:BaseNode) " +
                "WHERE n2.nodeId IN $neighborIds " +
                "RETURN n1, r, n2";

            log.info("查询邻居节点所有关系: {}, 参数: {}", allNeighborRelationsQuery, params);
            Collection<Map<String, Object>> neighborRelationsRecords = neo4jClient.query(allNeighborRelationsQuery)
                    .bindAll(params)
                    .fetch()
                    .all();

            log.info("邻居节点所有关系查询结果记录数: {}", neighborRelationsRecords.size());

            // 处理邻居节点的所有关系
            for (Map<String, Object> relRecord : neighborRelationsRecords) {
                if (relRecord.get("n1") != null && relRecord.get("n2") != null && relRecord.get("r") != null) {
                    Map<String, Object> sourceMap = getNodeProperties(relRecord.get("n1"));
                    Map<String, Object> targetMap = getNodeProperties(relRecord.get("n2"));
                    Map<String, Object> relationshipMap = getRelationshipProperties(relRecord.get("r"));
                    
                    if (relationshipMap != null && sourceMap != null && targetMap != null && 
                            sourceMap.containsKey("nodeId") && targetMap.containsKey("nodeId")) {
                        try {
                            Long sourceId = Long.valueOf(sourceMap.get("nodeId").toString());
                            Long targetId = Long.valueOf(targetMap.get("nodeId").toString());
                            
                            // 添加边（如果源节点和目标节点不相同）
                            if (!sourceId.equals(targetId)) {
                                Map<String, Object> edge = new HashMap<>();
                                edge.put("sourceId", sourceId);
                                edge.put("targetId", targetId);
                                edge.put("type", relationshipMap.get("type"));
                                edge.put("name", relationshipMap.get("name"));
                                
                                uniqueEdges.add(edge);
                                log.info("添加邻居节点关系: 从{}到{}, 类型: {}, 名称: {}", 
                                        sourceId, targetId, relationshipMap.get("type"), relationshipMap.get("name"));
                            }
                        } catch (Exception e) {
                            log.error("处理邻居节点关系时出错: {}", e.getMessage());
                        }
                    }
                }
            }
        }
        
        log.info("子图唯一节点数: {}, 唯一边数: {}", uniqueNodes.size(), uniqueEdges.size());
        
        // 构建返回结果
        GraphDTO result = buildGraphDTO(uniqueNodes, uniqueEdges);
        log.info("返回图数据: 节点数: {}, 边数: {}", 
                result.getNodes() != null ? result.getNodes().size() : 0, 
                result.getEdges() != null ? result.getEdges().size() : 0);
        return result;
    }
    
    @Override
    public Map<String, Object> getNodeProperties(Long nodeId) {
        Map<String, Object> params = new HashMap<>();
        params.put("nodeId", nodeId);
        
        // 查询节点
        String query = 
            "MATCH (n:BaseNode) " +
            "WHERE n.nodeId = $nodeId " +
            "RETURN n";
            
        log.info("执行查询节点属性: " + query + ", 参数: " + params);
        
        Collection<Map<String, Object>> records = neo4jClient.query(query)
                .bindAll(params)
                .fetch()
                .all();
                
        if (records.isEmpty()) {
            return null;
        }
        
        Map<String, Object> record = records.iterator().next();
        if (record.get("n") == null) {
            return null;
        }
        
        return getNodeProperties(record.get("n"));
    }
    
    /**
     * 构建GraphDTO对象
     * @param uniqueNodes 节点集合
     * @param uniqueEdges 边集合
     * @return 构建的GraphDTO对象
     */
    private GraphDTO buildGraphDTO(Map<Long, Map<String, Object>> uniqueNodes, Set<Map<String, Object>> uniqueEdges) {
        GraphDTO graphDTO = new GraphDTO();
        
        // 转换节点
        List<NodeDTO> nodeDTOs = uniqueNodes.values().stream()
                .map(node -> {
                    // 获取节点类型（第一个非BaseNode的标签）
                    List<String> labels = (List<String>) node.get("labels");
                    String type = "Node";
                    if (labels != null) {
                        for (String label : labels) {
                            if (!label.equals("BaseNode")) {
                                type = label;
                                break;
                            }
                        }
                    }
                    
                    return NodeDTO.builder()
                            .id(String.valueOf(node.get("nodeId")))
                            .label((String) node.get("name"))
                            .type(type)
                            .description((String) node.get("description"))
                            .color((String) node.get("color"))
                            .size(node.get("size") != null ? 
                                    Integer.parseInt(node.get("size").toString()) : null)
                            .build();
                })
                .collect(Collectors.toList());
        
        // 转换边
        List<EdgeDTO> edgeDTOs = uniqueEdges.stream()
                .map(edge -> EdgeDTO.builder()
                        .source(String.valueOf(edge.get("sourceId")))
                        .target(String.valueOf(edge.get("targetId")))
                        .type((String) edge.get("type"))
                        .name((String) edge.get("name"))
                        .build()
                )
                .collect(Collectors.toList());
        
        graphDTO.setNodes(nodeDTOs);
        graphDTO.setEdges(edgeDTOs);
        
        return graphDTO;
    }
    
    /**
     * 从Neo4j节点对象获取属性Map
     * @param nodeObj Neo4j节点对象
     * @return 属性Map
     */
    private Map<String, Object> getNodeProperties(Object nodeObj) {
        if (nodeObj == null) {
            return null;
        }
        
        try {
            Map<String, Object> result = new HashMap<>();
            if (nodeObj instanceof Map) {
                return (Map<String, Object>) nodeObj;
            } else if (nodeObj instanceof Node) {
                Node node = (Node) nodeObj;
                node.keys().forEach(key -> result.put(key, node.get(key).asObject()));
                
                // 确保nodeId存在且以Long类型存储
                if (node.containsKey("nodeId")) {
                    // 使用asObject()而不是asString()，避免类型转换问题
                    Object nodeIdValue = node.get("nodeId").asObject();
                    if (nodeIdValue instanceof Long) {
                        result.put("nodeId", nodeIdValue);
                    } else if (nodeIdValue instanceof Integer) {
                        result.put("nodeId", ((Integer) nodeIdValue).longValue());
                    } else if (nodeIdValue instanceof String) {
                        try {
                            result.put("nodeId", Long.parseLong((String) nodeIdValue));
                        } catch (NumberFormatException e) {
                            log.error("无法将nodeId转换为Long: " + nodeIdValue);
                            return null;
                        }
                    } else {
                        log.error("未知的nodeId类型: " + nodeIdValue.getClass());
                        return null;
                    }
                } else {
                    log.error("节点缺少nodeId属性");
                    return null;
                }
                
                List<String> labels = new ArrayList<>();
                node.labels().forEach(labels::add);
                result.put("labels", labels);
            }
            return result;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }
    
    /**
     * 从Neo4j关系对象获取属性Map
     * @param relObj Neo4j关系对象
     * @return 属性Map
     */
    private Map<String, Object> getRelationshipProperties(Object relObj) {
        if (relObj == null) {
            return null;
        }
        
        try {
            Map<String, Object> result = new HashMap<>();
            if (relObj instanceof Map) {
                return (Map<String, Object>) relObj;
            } else if (relObj instanceof Relationship) {
                Relationship rel = (Relationship) relObj;
                rel.keys().forEach(key -> result.put(key, rel.get(key).asObject()));
                result.put("type", rel.type());
                
                // 如果没有name属性，使用type作为默认值
                if (!result.containsKey("name")) {
                    result.put("name", rel.type());
                }
            }
            return result;
        } catch (Exception e) {
            e.printStackTrace();
            log.error("处理关系属性时出错: " + e.getMessage());
            return null;
        }
    }

    @Override
    public GraphDTO getAllNodesAndRelationships() {
        log.info("获取所有节点和关系");
        
        // 首先尝试从Redis缓存获取
        Object cachedData = redisTemplate.opsForValue().get(RedisGraphConstant.ALL_NODES_RELATIONSHIPS_KEY);
        if (cachedData != null) {
            log.info("从Redis缓存获取所有节点和关系数据");
            return (GraphDTO) cachedData;
        }
        
        log.info("缓存未命中，从数据库查询所有节点和关系");
        
        // 查询所有节点和关系
        String query = 
            "MATCH (n:BaseNode) " +
            "OPTIONAL MATCH (n)-[r]-(m:BaseNode) " +
            "WHERE ID(n) < ID(m) " + // 避免重复的关系
            "RETURN n, r, m";
            
        Collection<Map<String, Object>> records = neo4jClient.query(query)
                .fetch()
                .all();
                
        log.info("查询结果记录数: {}", records.size());
        
        // 用于存储唯一节点和边的集合
        Map<Long, Map<String, Object>> uniqueNodes = new HashMap<>();
        Set<Map<String, Object>> uniqueEdges = new HashSet<>();
        
        // 处理查询结果
        for (Map<String, Object> record : records) {
            // 处理源节点
            if (record.get("n") != null) {
                Map<String, Object> nodeMap = getNodeProperties(record.get("n"));
                if (nodeMap != null && nodeMap.containsKey("nodeId")) {
                    try {
                        Long nodeId = Long.valueOf(nodeMap.get("nodeId").toString());
                        uniqueNodes.put(nodeId, nodeMap);
                    } catch (Exception e) {
                        log.error("处理节点ID时出错: {}, 错误: {}", nodeMap.get("nodeId"), e.getMessage());
                    }
                }
            }
            
            // 处理目标节点
            if (record.get("m") != null) {
                Map<String, Object> targetNodeMap = getNodeProperties(record.get("m"));
                if (targetNodeMap != null && targetNodeMap.containsKey("nodeId")) {
                    try {
                        Long targetNodeId = Long.valueOf(targetNodeMap.get("nodeId").toString());
                        uniqueNodes.put(targetNodeId, targetNodeMap);
                    } catch (Exception e) {
                        log.error("处理目标节点ID时出错: {}, 错误: {}", targetNodeMap.get("nodeId"), e.getMessage());
                        continue;
                    }
                } else {
                    continue;
                }
                
                // 处理关系
                if (record.get("r") != null && record.get("n") != null) {
                    Map<String, Object> relationshipMap = getRelationshipProperties(record.get("r"));
                    Map<String, Object> sourceNodeMap = getNodeProperties(record.get("n"));
                    
                    if (relationshipMap != null && sourceNodeMap != null && 
                            sourceNodeMap.containsKey("nodeId") && targetNodeMap.containsKey("nodeId")) {
                        try {
                            Long sourceId = Long.valueOf(sourceNodeMap.get("nodeId").toString());
                            Long targetId = Long.valueOf(targetNodeMap.get("nodeId").toString());
                            
                            Map<String, Object> edge = new HashMap<>();
                            edge.put("sourceId", sourceId);
                            edge.put("targetId", targetId);
                            edge.put("type", relationshipMap.get("type"));
                            edge.put("name", relationshipMap.get("name"));
                            
                            uniqueEdges.add(edge);
                        } catch (Exception e) {
                            log.error("处理边时出错: {}", e.getMessage());
                        }
                    }
                }
            }
        }
        
        log.info("唯一节点数: {}, 唯一边数: {}", uniqueNodes.size(), uniqueEdges.size());
        
        // 构建返回结果
        GraphDTO result = buildGraphDTO(uniqueNodes, uniqueEdges);
        
        // 将结果存入Redis缓存
        redisTemplate.opsForValue().set(
                RedisGraphConstant.ALL_NODES_RELATIONSHIPS_KEY, 
                result, 
                RedisGraphConstant.GRAPH_DATA_EXPIRE, 
                TimeUnit.SECONDS
        );
        
        return result;
    }
    
    /**
     * 获取所有课程和前置课程关系，用于图的初始化
     * 该方法仅查询Course节点及其PRE_COURSE关系
     * @return 包含所有课程节点和前置课程关系的图数据
     */
    @Override
    public GraphDTO getCoursesWithPreCourseRelationships() {
        log.info("查询所有课程和前置课程关系图数据");
        
        // 查询所有课程节点和前置课程关系
        String query = 
            "MATCH (c:Course) " +
            "OPTIONAL MATCH (c1:Course)-[r:PRE_COURSE]->(c2:Course) " +
            "RETURN c, r, c1, c2";
        
        Collection<Map<String, Object>> records = neo4jClient.query(query)
                .fetch()
                .all();
                
        log.info("查询到 {} 条记录", records.size());
        
        // 用于存储唯一节点和边的集合
        Map<Long, Map<String, Object>> uniqueNodes = new HashMap<>();
        Set<Map<String, Object>> uniqueEdges = new HashSet<>();
        
        // 处理查询结果
        for (Map<String, Object> record : records) {
            // 处理所有课程节点
            processNodeFromRecord(record, "c", uniqueNodes);
            processNodeFromRecord(record, "c1", uniqueNodes);
            processNodeFromRecord(record, "c2", uniqueNodes);
            
            // 处理前置课程关系
            if (record.get("r") != null && record.get("c1") != null && record.get("c2") != null) {
                Map<String, Object> relationshipMap = getRelationshipProperties(record.get("r"));
                Map<String, Object> sourceNodeMap = getNodeProperties(record.get("c1"));
                Map<String, Object> targetNodeMap = getNodeProperties(record.get("c2"));
                
                if (relationshipMap != null && sourceNodeMap != null && targetNodeMap != null && 
                        sourceNodeMap.containsKey("nodeId") && targetNodeMap.containsKey("nodeId")) {
                    try {
                        Long sourceId = Long.valueOf(sourceNodeMap.get("nodeId").toString());
                        Long targetId = Long.valueOf(targetNodeMap.get("nodeId").toString());
                        
                        Map<String, Object> edge = new HashMap<>();
                        edge.put("sourceId", sourceId);
                        edge.put("targetId", targetId);
                        edge.put("type", relationshipMap.get("type"));
                        edge.put("name", relationshipMap.get("name"));
                        
                        uniqueEdges.add(edge);
                        log.debug("添加前置课程关系边: 从 {} 到 {}", sourceId, targetId);
                    } catch (Exception e) {
                        log.error("处理前置课程关系边时出错: {}", e.getMessage(), e);
                    }
                }
            }
        }
        
        log.info("构建图数据: 唯一节点数: {}, 唯一边数: {}", uniqueNodes.size(), uniqueEdges.size());
        
        // 构建返回结果
        return buildGraphDTO(uniqueNodes, uniqueEdges);
    }
    
    /**
     * 从记录中处理节点并添加到唯一节点集合
     * @param record 查询记录
     * @param fieldName 字段名
     * @param uniqueNodes 唯一节点集合
     */
    private void processNodeFromRecord(Map<String, Object> record, String fieldName, Map<Long, Map<String, Object>> uniqueNodes) {
        if (record.get(fieldName) != null) {
            Map<String, Object> nodeMap = getNodeProperties(record.get(fieldName));
            if (nodeMap != null && nodeMap.containsKey("nodeId")) {
                try {
                    Long nodeId = Long.valueOf(nodeMap.get("nodeId").toString());
                    uniqueNodes.put(nodeId, nodeMap);
                    log.debug("处理节点 {}: ID={}", fieldName, nodeId);
                } catch (Exception e) {
                    log.error("处理节点 {} ID时出错: {}", fieldName, e.getMessage(), e);
                }
            }
        }
    }
    
    @Override
    public List<String> getAllNodeTypes() {
        log.info("获取所有BaseNode节点的非BaseNode标签类型");
        
        // 查询所有节点标签
        String query = 
            "MATCH (n:BaseNode) " +
            "WITH labels(n) AS nodeLabels " +
            "UNWIND nodeLabels AS label " +
            "WITH label " +
            "WHERE label <> 'BaseNode' " +
            "RETURN DISTINCT label " +
            "ORDER BY label";
            
        Collection<Map<String, Object>> records = neo4jClient.query(query)
                .fetch()
                .all();
                
        log.info("查询到 {} 种不同类型的节点标签", records.size());
        
        // 提取所有非BaseNode的标签类型
        List<String> nodeTypes = records.stream()
                .map(record -> (String) record.get("label"))
                .collect(Collectors.toList());
                
        return nodeTypes;
    }
}